using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Security;
using RecruitmentAgency.Models.DataTypes;
using RecruitmentAgency.Models.Utilities;

namespace RecruitmentAgency.Models.DataProviders
{
    /// <summary>
    /// The RecruitmentAgency.Controllers.AccountDataProvider class defines the methods and property required forthe registration and login
    /// </summary>
    public class AccountDataProvider : BaseDataProvider, IAccountDataProvider
    {                
        
        /// <summary>
        /// This method check if the username typed by the user is unique
        /// </summary>
        /// <param name="userName">The username typed by the user</param>
        /// <returns>Returns true if the username is unique</returns>
        public bool UserNameIsUnique(string userName)
        {
            try
            {
                bool? success = false;
                DataContext.up_UsernameIsUnique(userName, ref success);
                return (bool)success;
            }
            catch (Exception ex)
            {
                DataProvider.HandleException(ex);
            }
            return false;
        }

        /// <summary>
        /// Validate the user credential for the login
        /// </summary>
        /// <param name="userName">The user username</param>
        /// <param name="password">The user password</param>
        /// <returns>Returns true if the login is succesfull</returns>
        public bool ValidateUser(string userName, string password)
        {
            try
            {
                if (DataContext.up_GetSaltByUsername(userName).Count() > 0)
                {
                    byte[] salt = (byte[])((DataContext.up_GetSaltByUsername(userName).ElementAt(0).Salt).ToArray());
                    Dictionary<byte[], byte[]> encryptedPassword = Encryption.RestoreEncryptedPassword(userName, password, salt);
                    return ((int)DataContext.up_Login(userName, encryptedPassword.ElementAt(0).Value).ElementAt(0).Result > 0);
                }
            }
            catch (Exception ex)
            {
                DataProvider.HandleException(ex);                
            }            
            return false;                        
        }


        /// <summary>
        /// Gets the user salt key from the database according to the user username
        /// </summary>
        /// <param name="username">The user username</param>
        /// <returns>Returns the User salt Key</returns>
        public byte[] GetSaltByUsername(string username)
        {
            byte[] salt = null;
            try
            {
                salt = (byte[])((DataContext.up_GetSaltByUsername(username).ElementAt(0).Salt).ToArray());
            }
            catch (Exception ex)
            {
                DataProvider.HandleException(ex);
            }
            return salt;
        }


        /// <summary>
        /// Adda new Job seeker records to the database
        /// </summary>
        /// <param name="register">An instance of Register containing the Job seeker details</param>
        /// <returns>Returns an instance of the MembershipCreateStatus containing the result of the attempted registration</returns>
        public MembershipCreateStatus CreateUser(Register register)
        {
            MembershipCreateStatus status = MembershipCreateStatus.ProviderError;
            try
            {
                status = (MembershipCreateStatus)(DataContext.up_Register(register.RegisterTitle, register.RegisterFirstName, string.Empty/*get rid of middlenames from sp*/, register.RegisterLastName, register.PersonalEmail, "Personal e-mail", register.RegisterUserName, register.RegisterEncryptedPassword, register.RegisterSalt, 3));//user
            }
            catch (Exception ex)
            {
                DataProvider.HandleException(ex);
            }
            return status;
        }

        /// <summary>
        /// Adda new Job Provider records to the database
        /// </summary>
        /// <param name="jobProvider">An instance of Job Provider containing the company details</param>
        /// <returns>A MembershipCreateStatus instance containing the result of the attempted registration</returns>
        public MembershipCreateStatus CreateJobProvider(RegisterJobProvider jobProvider)
        {
            MembershipCreateStatus status = MembershipCreateStatus.ProviderError;
            try
            {                
                status = (MembershipCreateStatus)(DataContext.up_RegisterJobProvider(jobProvider.CompanyName, jobProvider.RegistrationNumber, jobProvider.AddressLine1, jobProvider.AddressLine2, jobProvider.Town, jobProvider.PostCode, jobProvider.Email, jobProvider.WebsiteUrl.ToLower().Replace("www.", string.Empty).Replace("http://", string.Empty), jobProvider.Title, jobProvider.FirstName, jobProvider.LastName, jobProvider.JobProviderUserName, jobProvider.EncryptedPassword, jobProvider.Salt));
            }
            catch (Exception ex)
            {
                DataProvider.HandleException(ex);
            }
            return status;
        }


      
        /// <summary>
        /// Translate the error returned by registration attempt in a message
        /// </summary>
        /// <param name="createStatus">The result of the attempted registration operation</param>
        /// <returns>Returns a message containing the reason for the failed registration</returns>
        public string ErrorCodeToString(MembershipCreateStatus createStatus)
        {
            // See http://msdn.microsoft.com/en-us/library/system.web.security.membershipcreatestatus.aspx for
            // a full list of status codes.
            switch (createStatus)
            {
                case MembershipCreateStatus.DuplicateUserName:
                    return "Username already exists. Please enter a different user name.";

                case MembershipCreateStatus.DuplicateEmail:
                    return "A username for that e-mail address already exists. Please enter a different e-mail address.";

                case MembershipCreateStatus.InvalidPassword:
                    return "The password provided is invalid. Please enter a valid password value.";

                case MembershipCreateStatus.InvalidEmail:
                    return "The e-mail address provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidAnswer:
                    return "The password retrieval answer provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidQuestion:
                    return "The password retrieval question provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidUserName:
                    return "The user name provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.ProviderError:
                    return "The authentication provider returned an error. Please verify your entry and try again. If the problem persists, please contact your system administrator.";

                case MembershipCreateStatus.UserRejected:
                    return "The user creation request has been canceled. Please verify your entry and try again. If the problem persists, please contact your system administrator.";

                default:
                    return "An unknown error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
            }
        }
    }
}